package com.ophiux.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ophiux.common.core.base.Result;
import com.ophiux.common.core.enums.ResultEnum;
import com.ophiux.product.mapper.ProductMapper;
import com.ophiux.product.model.dto.ProductDTO;
import com.ophiux.product.model.entity.Product;
import com.ophiux.product.model.vo.ProductAddVo;
import com.ophiux.product.model.vo.ProductQueryVo;
import com.ophiux.product.model.vo.ProductUpdateVo;
import com.ophiux.product.service.IProductService;
import io.seata.core.context.RootContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {

    @Override
    public IPage<ProductDTO> getPage(IPage<Product> iPage, ProductQueryVo queryDTO) {
        LambdaQueryWrapper<Product> lambda = new LambdaQueryWrapper<Product>();
        IPage<Product> page = this.page(iPage, lambda);
        return page.convert(item -> {
            ProductDTO dto = new ProductDTO();
            BeanUtils.copyProperties(item,dto);
            return dto;
        });
    }

    @Override
    public Result insert(ProductAddVo vo) {
        Product data = new Product();
        BeanUtils.copyProperties(vo,data);
        int effCount = this.baseMapper.insert(data);
        if (effCount > 0) return Result.success();
        return Result.fail();
    }

    @Override
    public Result update(ProductUpdateVo vo) {
        Product data = this.getById(vo.getId());
        if (data == null) return Result.fail(ResultEnum.DATA_NOT_FOUND);

        BeanUtils.copyProperties(vo, data);
        boolean isSuccess = this.updateById(data);
        if (!isSuccess) return Result.fail(ResultEnum.DATA_UPDATE_FAIL);

        return Result.success(ResultEnum.requestSuccess);
    }


    @Override
    public Result delete(String ids) {
        List<Integer> list = Arrays.stream(ids.split(",")).map(Integer::parseInt).collect(Collectors.toList());
        boolean effCount = removeByIds(list);
        if (effCount) return Result.success();
        return Result.fail();
    }


    @Autowired
    ApplicationContext applicationContext;

    volatile Integer couNum = 0;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateStock(Integer stockNum, Integer productId) {
        log.info("product begin ... xid: " + RootContext.getXID());
        int effCount = this.baseMapper.updateStock(stockNum, productId);

        try {
//            ProductServiceImpl service = applicationContext.getBean(ProductServiceImpl.class);
//            int i = service.addStock(10, productId);
        }catch (Exception e){
            e.printStackTrace();
        }
        couNum++;
        System.out.println(couNum);
        return Result.success();
    }

//    @Transactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)
    public int addStock(Integer stockNum, Integer productId){
        log.info("增加库存10");
        int i2 = this.baseMapper.addStock(stockNum, productId);
        int dddd = 1/0;
        return 1;
        /**
         * REQUIRED         当前存在事务，则加入改事务；如果当前没有事务，则新建一个新的事务
         * REQUIRE_NEW      不管是否存在事务，都会新开一个事务，新老事务相互独立。外部事务抛出异常回滚不会影响内部事务的正常提交。
         * NESTED           如果当前存在事务，则嵌套在当前事务中执行。如果当前没有事务，则新建一个事务，类似于 REQUIRE_NEW
         * SUPPORTS         表示支持当前事务，如果当前不存在事务，以非事务的方式执行
         * NOT_SUPPORTED    表示以非事务的方式来运行，如果当前存在事务，则把当前事务挂起
         * MANDATORY        强制事务执行，若当前不存在事务，则抛出异常
         * NEVER            以非事务的方式执行，如果当前存在事务，则抛出异常
         *
         */
    }

}
